<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    // 普通函数封装的缺点:
    // (1) 通过函数cat创建的对象,和函数本身并无任何关系 (Cat不是构造函数)
    // var arr = new Array(1, 2, 3);
    // console.log(arr instanceof Array);

    // var obj = new Object({ a: 1, b: 2 });
    // console.log(obj instanceof Object);

    // 分析:
    // (1) 如果想让创建的对象和函数有关联, 一般用构造函数 (创建实例化对象)
    // (2) 对比发现,构造函数也是一个函数, 配合new关键词创建实例化对象


    // 构造函数:
    // (1) 官方提供的构造函数:   Array()  Object() Date() Promise()  Error()  Set()  Map()
    // (2) 用户自定义构造函数:  new Xxx();


    // new 关键词做了哪些操作:
    // (1) 创建一个纯净的实例化对象  {}
    // (2) 给创建的实例化对象绑定原型属性([[Prototype]])指向构造函数的原型对象(构造函数.prototype),所有的(该构造函数创建的)实例化对象都可以通过此属性访问构造函数的原型对象
    // (3) this -> {}  强制将构造函数内的this指向本次构造函数执行过程中创建的实例化对象 (通过this给实例化对象绑定数据和方法)
    // (4) return this 返回被创建的实例化对象

    // 注意:
    // (1) 为了区分普通函数和构造函数,建议构造函数首字符大写
    // (2) 每次调用构造函数都会重新执行构造函数的上下文,返回被创建的实例化对象
    // (3) 构造函数中的this, 指向本次构造函数执行过程中创建的实例化对象


    // 普通函数
    // function fn() {
    //     console.log("函数fn执行了", this); // window
    // }

    // var result = fn();
    // console.log("result", result); // undefined


    // 构造函数(用户自定义构造函数)
    function Fn() {
        //  {}
        //  {}[[Prototype]] = Fn.prototype;  // 给实例化对象绑定原型属性([[Prototype]])指向构造函数的原型对象(Fn.prototype),所有的实例化对象都可以通过此属性访问构造函数的原型对象(Fn.prototype)  => 浅复制
        //  this -> {}
        console.log("函数Fn执行了", this); // this -> {}

        // 给构造函数创建的实例化对象绑定属性和方法(用户自己决定)
        this.a = 1;
        this.b = 2;
        this.sum = function () { // 匿名函数中的this(实例化对象)
            console.log(this.a + this.b);
        }


        // return this;  返回被创建的实例化对象
    }

    Fn.prototype.sum = function () {
        return this.a + this.b;
    }


    var result = new Fn();  // 调用构造函数,执行构造函数上下文,返回被创建的实例化对象 => 赋值给变量result
    console.log("result", result, result instanceof Fn); //{}



    // var result = new Fn();  // 构造函数调用
    // console.log("result", result); //{}









</script>

</html>